#include <stdio.h>
#include <stdlib.h>
#include <string.h>
	
struct student {
	int id;
    char sex;
    int age;
};

#define offset(type, member) (&(((type *)0)->member))
#define struct_base(ptr, type, member) \
    ( (type *) ( (char *)ptr - offset(type, member) ) )

/*
 * 通过结构体的一个成员获取结构的指针
 * @ptr： 指向成员的指针
 * @type: 结构类型
 * @member: 成员名
 * 定义于linux/kernel.h
 */ 
#define container_of(ptr, type, member) ({ \
    const typeof( ((type *)0)->member ) *_mptr = (ptr); \
    (type *) ( (char *)_mptr - offset(type, member) );  \
})



// 传入成员地址，可以知道对应的值，更隐含了成员的存储位置
// 我们可以根据该成员的位置，找到结构的首地址，从而访问其它成员

// 应用场景：不是自己自定义的结构，想要访问结构的其它成员
void get_id(char *sex) {
    //struct student *p = struct_base(sex, struct student, sex);
    struct student *p = container_of(sex, struct student, sex);
    printf("get id:%d\n", p->id); 
}

int main () {
    // 计算成员变量在结构内的偏移
    printf("&id  = %p\n", &( ((struct student *)0)->id  ));
    printf("&sex = %p\n", &( ((struct student *)0)->sex ));
    printf("&age = %p\n", &( ((struct student *)0)->age ));
    
    // 已经结构中某个成员的偏移，如何得到该结构体的首地址
    struct student stu = {123234, 'm', 15};
    struct student *p = struct_base(&stu.sex, struct student, sex);
    printf("age:%d\n", p->age); 
    
    get_id(&stu.sex);
    return 0;
}
